package com.bestv.search.common.dao.hibernate;

import com.bestv.search.common.dao.GenericDao;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import java.io.Serializable;
import java.util.List;

public class GenericDaoHibernate<T, PK extends Serializable> extends HibernateDaoSupport implements GenericDao<T, PK> {

    protected final Log log = LogFactory.getLog(getClass());

    private Class<T> persistentClass;

    public GenericDaoHibernate() {
    }

    public GenericDaoHibernate(final Class<T> persistentClass) {
        this.persistentClass = persistentClass;
    }

    @SuppressWarnings("unchecked")
    public boolean exists(PK id) {
        T entity = (T) super.getHibernateTemplate().get(persistentClass, id);
        return entity != null;
    }

    @SuppressWarnings("unchecked")
    public T get(PK id) {
        T entity = (T) getHibernateTemplate().get(persistentClass, id);
        if (entity == null) {
            log.warn("Uh oh, '" + this.persistentClass + "' object with id '" + id + "' not found...");
            throw new ObjectRetrievalFailureException(this.persistentClass, id);
        }
        return entity;
    }

    @SuppressWarnings("unchecked")
    public List<T> getAll() {
        return getHibernateTemplate().loadAll(persistentClass);
    }

    @SuppressWarnings("unchecked")
    public T remove(PK id) {
        T entity = (T) super.getHibernateTemplate().get(persistentClass, id);
        if (entity != null) {
            getHibernateTemplate().delete(entity);
            return entity;
        } else {
            log.debug(persistentClass.getName() + "'" + id + "' is not existed");
            return entity;
        }
    }

    @SuppressWarnings("unchecked")
    public T save(T object) {
        return (T) getHibernateTemplate().merge(object);
    }

    public T saveOrUpdate(T object) {
        super.getHibernateTemplate().saveOrUpdate(object);
        return object;
    }

    public void saveObjectList(List<T> list) {
        super.getHibernateTemplate().saveOrUpdateAll(list);
    }

    public void removeObjectList(List<T> list) {
        super.getHibernateTemplate().deleteAll(list);
    }

    public T update(T object) {
        getHibernateTemplate().update(object);
        return object;
    }
}